package cn.enjoy.dynamic.datasource.aspect;

import cn.enjoy.dynamic.datasource.annotation.DataSource;
import cn.enjoy.dynamic.datasource.config.DynamicContextHolder;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * @author K
 * @date 2020/12/14 15:28
 */
@Aspect
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class DataSourceAspect {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Pointcut("@within(cn.enjoy.dynamic.datasource.annotation.DataSource) || @annotation(cn.enjoy.dynamic.datasource.annotation.DataSource)")

    public void dataSourcePointCut() {
    }

    /**
     * 流程：请求进来线程设置 DynamicContextHolder.push(value) -> determineCurrentLookupKey()决定使用的数据源 -> DynamicContextHolder.poll();线程删除第一个元素
     *
     * @param point 切点
     * @return Object
     * @throws Throwable 抛出异常
     */
    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 被拦截的方法
        MethodSignature methodSignature = (MethodSignature) point.getSignature();
        Method method = methodSignature.getMethod();
        // 被拦截的类
        Class<?> targetClass = point.getTarget().getClass();

        DataSource classAnnotation = targetClass.getAnnotation(DataSource.class);
        DataSource methodAnnotation = method.getAnnotation(DataSource.class);

        if (classAnnotation != null || methodAnnotation != null) {
            String value;
            if (classAnnotation != null) {
                value = classAnnotation.value();
            } else {
                value = methodAnnotation.value();
            }
            DynamicContextHolder.push(value);
        }
        try {
            return point.proceed();
        } finally {
            // 最后删除当前线程队列第一个元素，如果队列为空，也将清空当前线程中存储的变量
//            DynamicContextHolder.poll();
//            logger.info(" datasource close");
        }

    }
}
